load("@buildifier_prebuilt//:rules.bzl", "buildifier", "buildifier_test")
load("@com_github_ash2k_bazel_tools//multirun:def.bzl", "multirun")
load("@gazelle//:def.bzl", "gazelle")
load("//bazel/ci:go_bin_for_host.bzl", "go_bin_for_host")
load("//bazel/ci:proto_targets.bzl", "proto_targets")
load("//bazel/sh:def.bzl", "noop_warn", "repo_command", "sh_template")

required_tags = [
    "e2e",
    "integration",
]

gazelle(
    name = "gazelle_generate",
    build_tags = required_tags,
)

gazelle(
    name = "gazelle_check",
    build_tags = required_tags,
    command = "fix",
    mode = "diff",
)

buildifier_test(
    name = "buildifier_check",
    timeout = "short",
    lint_mode = "warn",
    lint_warnings = ["all"],
    mode = "diff",
    no_sandbox = True,
    tags = ["no-remote-exec"],
    verbose = True,
    workspace = "//:WORKSPACE.bzlmod",
)

buildifier(
    name = "buildifier_fix",
    lint_mode = "fix",
    lint_warnings = ["all"],
    mode = "fix",
    tags = ["no-remote-exec"],
    verbose = True,
)

sh_template(
    name = "keep_sorted",
    data = [
        "@com_github_google_keep_sorted//:keep-sorted",
    ],
    substitutions = {
        "@@KEEP_SORTED@@": "$(rootpath @com_github_google_keep_sorted//:keep-sorted)",
    },
    template = "keep_sorted.sh.in",
)

sh_template(
    name = "go_mod_tidy",
    data = [
        ":go_bin_for_host",
    ],
    substitutions = {
        "@@GO@@": "$(rootpath :go_bin_for_host)",
    },
    template = "go_tidy.sh.in",
)

sh_template(
    name = "shfmt",
    data = [
        "@com_github_katexochen_sh_v3//cmd/shfmt",
    ],
    substitutions = {
        "@@SHFMT@@": "$(rootpath @com_github_katexochen_sh_v3//cmd/shfmt)",
    },
    template = "shfmt.sh.in",
)

noop_warn(
    name = "shellcheck_noop_warning",
    warning = "Shellcheck should have been executed, but is currently not available for your platform.",
)

alias(
    name = "com_github_koalaman_shellcheck",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_koalaman_shellcheck_darwin_amd64//:shellcheck",
        "@io_bazel_rules_go//go/platform:darwin_arm64": ":shellcheck_noop_warning",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_koalaman_shellcheck_linux_amd64//:shellcheck",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_koalaman_shellcheck_linux_arm64//:shellcheck",
    }),
)

sh_template(
    name = "shellcheck",
    data = [
        ":com_github_koalaman_shellcheck",
        "@com_github_katexochen_sh_v3//cmd/shfmt",
    ],
    substitutions = {
        "@@SHELLCHECK@@": "$(rootpath :com_github_koalaman_shellcheck)",
        "@@SHFMT@@": "$(rootpath @com_github_katexochen_sh_v3//cmd/shfmt)",
    },
    template = "shellcheck.sh.in",
)

alias(
    name = "com_github_rhysd_actionlint",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_rhysd_actionlint_darwin_amd64//:actionlint",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_rhysd_actionlint_darwin_arm64//:actionlint",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_rhysd_actionlint_linux_amd64//:actionlint",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_rhysd_actionlint_linux_arm64//:actionlint",
    }),
)

sh_template(
    name = "actionlint",
    data = [
        ":com_github_koalaman_shellcheck",
        ":com_github_rhysd_actionlint",
    ],
    substitutions = {
        "@@ACTIONLINT@@": "$(rootpath :com_github_rhysd_actionlint)",
        "@@SHELLCHECK@@": "$(rootpath :com_github_koalaman_shellcheck)",
    },
    template = "actionlint.sh.in",
)

repo_command(
    name = "actionlint_no_shellcheck",
    command = ":com_github_rhysd_actionlint",
)

alias(
    name = "com_github_mvdan_gofumpt",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_mvdan_gofumpt_darwin_amd64//file",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_mvdan_gofumpt_darwin_arm64//file",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_mvdan_gofumpt_linux_amd64//file",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_mvdan_gofumpt_linux_arm64//file",
    }),
)

repo_command(
    name = "gofumpt",
    args = [
        "-l",
        "-w",
        ".",
    ],
    command = ":com_github_mvdan_gofumpt",
)

alias(
    name = "com_github_aquasecurity_tfsec",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_aquasecurity_tfsec_darwin_amd64//:tfsec",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_aquasecurity_tfsec_darwin_arm64//:tfsec",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_aquasecurity_tfsec_linux_amd64//:tfsec",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_aquasecurity_tfsec_linux_arm64//:tfsec",
    }),
)

sh_template(
    name = "tfsec",
    data = [
        ":com_github_aquasecurity_tfsec",
    ],
    substitutions = {
        "@@TFSEC@@": "$(rootpath :com_github_aquasecurity_tfsec)",
    },
    template = "tfsec.sh.in",
)

alias(
    name = "com_github_hashicorp_terraform",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_hashicorp_terraform_darwin_amd64//:terraform",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_hashicorp_terraform_darwin_arm64//:terraform",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_hashicorp_terraform_linux_amd64//:terraform",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_hashicorp_terraform_linux_arm64//:terraform",
    }),
    visibility = ["//visibility:public"],
)

sh_template(
    name = "terraform_gen",
    data = [
        ":com_github_hashicorp_terraform",
    ],
    substitutions = {
        "@@MODE@@": "generate",
        "@@TERRAFORM@@": "$(rootpath :com_github_hashicorp_terraform)",
    },
    template = "terraform.sh.in",
)

sh_template(
    name = "terraform_check",
    data = [
        ":com_github_hashicorp_terraform",
    ],
    substitutions = {
        "@@MODE@@": "check",
        "@@TERRAFORM@@": "$(rootpath :com_github_hashicorp_terraform)",
    },
    template = "terraform.sh.in",
)

sh_template(
    name = "terraform_fmt",
    data = [
        ":com_github_hashicorp_terraform",
    ],
    substitutions = {
        "@@MODE@@": "format",
        "@@TERRAFORM@@": "$(rootpath :com_github_hashicorp_terraform)",
    },
    template = "terraform.sh.in",
)

alias(
    name = "com_github_golangci_golangci_lint",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_golangci_golangci_lint_darwin_amd64//:golangci_lint_bin",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_golangci_golangci_lint_darwin_arm64//:golangci_lint_bin",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_golangci_golangci_lint_linux_amd64//:golangci_lint_bin",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_golangci_golangci_lint_linux_arm64//:golangci_lint_bin",
    }),
)

sh_template(
    name = "golangci_lint",
    data = [
        ":com_github_golangci_golangci_lint",
        ":go_bin_for_host",
    ],
    substitutions = {
        "@@GO@@": "$(rootpath :go_bin_for_host)",
        "@@GOLANGCI-LINT@@": "$(rootpath :com_github_golangci_golangci_lint)",
    },
    template = "golangci_lint.sh.in",
)

alias(
    name = "com_github_bufbuild_buf",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_bufbuild_buf_darwin_amd64//:buf",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_bufbuild_buf_darwin_arm64//:buf",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_bufbuild_buf_linux_amd64//:buf",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_bufbuild_buf_linux_arm64//:buf",
    }),
)

sh_template(
    name = "buf_fmt",
    data = [
        ":com_github_bufbuild_buf",
    ],
    substitutions = {
        "@@BUF@@": "$(rootpath :com_github_bufbuild_buf)",
    },
    template = "buf.sh.in",
)

sh_template(
    name = "golicenses_check",
    data = [
        ":go_bin_for_host",
        "@com_github_google_go_licenses//:go-licenses",
    ],
    substitutions = {
        "@@GO@@": "$(rootpath :go_bin_for_host)",
        "@@GO_LICENSES@@": "$(rootpath @com_github_google_go_licenses//:go-licenses)",
    },
    template = "golicenses.sh.in",
)

sh_template(
    name = "license_header_check",
    data = [],
    substitutions = {},
    template = "license_header.sh.in",
)

sh_template(
    name = "govulncheck",
    data = [
        ":go_bin_for_host",
        "@jq_toolchains//:resolved_toolchain",
        "@org_golang_x_vuln//cmd/govulncheck",
    ],
    substitutions = {
        "@@GO@@": "$(rootpath :go_bin_for_host)",
        "@@GOVULNCHECK@@": "$(rootpath @org_golang_x_vuln//cmd/govulncheck:govulncheck)",
        "@@JQ@@": "$(rootpath @jq_toolchains//:resolved_toolchain)",
    },
    template = "govulncheck.sh.in",
)

alias(
    name = "com_github_siderolabs_talos_hack_docgen",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_siderolabs_talos_hack_docgen_darwin_amd64//file",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_siderolabs_talos_hack_docgen_darwin_arm64//file",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_siderolabs_talos_hack_docgen_linux_amd64//file",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_siderolabs_talos_hack_docgen_linux_arm64//file",
    }),
)

alias(
    name = "com_github_helm_helm",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_helm_helm_darwin_amd64//:helm",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_helm_helm_darwin_arm64//:helm",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_helm_helm_linux_amd64//:helm",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_helm_helm_linux_arm64//:helm",
    }),
)

sh_template(
    name = "go_generate",
    data = [
        ":com_github_helm_helm",
        ":com_github_siderolabs_talos_hack_docgen",
        ":go_bin_for_host",
        "//internal/attestation/measurements/measurement-generator",
        "//internal/versions/hash-generator",
        "@org_golang_x_tools//cmd/stringer",
        "@yq_toolchains//:resolved_toolchain",
    ],
    substitutions = {
        "@@DOCGEN@@": "$(rootpath :com_github_siderolabs_talos_hack_docgen)",
        "@@GO@@": "$(rootpath :go_bin_for_host)",
        "@@HASH_GENERATOR@@": "$(rootpath //internal/versions/hash-generator:hash-generator)",
        "@@HELM@@": "$(rootpath :com_github_helm_helm)",
        "@@MEASUREMENT_GENERATOR@@": "$(rootpath //internal/attestation/measurements/measurement-generator:measurement-generator)",
        "@@STRINGER@@": "$(rootpath @org_golang_x_tools//cmd/stringer:stringer)",
        "@@YQ@@": "$(rootpath @yq_toolchains//:resolved_toolchain)",
    },
    template = "go_generate.sh.in",
)

# deps_mirror_fix fixes bazel workspace rules for external dependencies.
# It normalizes the rules and rewrites WORKSPACE and bzl files.
# If files are not in the mirror, it will fail.
# Use deps_mirror_upload to upload missing files.
repo_command(
    name = "deps_mirror_fix",
    args = [
        "fix",
        "--unauthenticated",
    ],
    command = "//hack/bazel-deps-mirror",
)

# deps_mirror_upload fixes bazel workspace rules for external dependencies.
# It uploads all dependencies to the mirror, normalizes the rules and rewrites WORKSPACE and bzl files.
repo_command(
    name = "deps_mirror_upload",
    args = [
        "fix",
    ],
    command = "//hack/bazel-deps-mirror",
)

# deps_mirror_upgrade upgrades bazel workspace rules for external dependencies.
# Users are supposed to replace any upstream URLs.
# It replaces the expected hash and uploads the new dep to the mirror.
repo_command(
    name = "deps_mirror_upgrade",
    args = [
        "upgrade",
    ],
    command = "//hack/bazel-deps-mirror",
)

# deps_mirror_check checks bazel workspace rules for external dependencies.
# It checks if all dependency rules have mirror urls and are properly formatted.
# It doesn't check if the mirror has the files.
# Use deps_mirror_check_mirror to check if the mirror has the files.
repo_command(
    name = "deps_mirror_check",
    args = [
        "check",
    ],
    command = "//hack/bazel-deps-mirror",
)

# deps_mirror_check_mirror checks bazel workspace rules for external dependencies.
# It checks if all dependency rules are correctly mirrored and checks that the rules are properly formatted.
repo_command(
    name = "deps_mirror_check_mirror",
    args = [
        "check",
        "--mirror",
    ],
    command = "//hack/bazel-deps-mirror",
)

sh_template(
    name = "proto_targets_check",
    data = [
        "@diffutils//:bin/diff",
    ],
    env = {
        "DIFF": "$(rootpath @diffutils//:bin/diff)",
    },
    substitutions = {
        "@@PROTO_TARGETS@@": " ".join(proto_targets()),
    },
    template = "proto_targets_check.sh.in",
)

multirun(
    name = "proto_generate",
    commands = proto_targets(),
    jobs = 0,  # execute concurrently
)

sh_template(
    name = "cli_docgen",
    data = [
        "//hack/clidocgen",
    ],
    substitutions = {
        "@@CLIDOCGEN@@": "$(rootpath //hack/clidocgen:clidocgen)",
    },
    template = "cli_docgen.sh.in",
)

sh_template(
    name = "terraform_docgen",
    data = [
        ":com_github_hashicorp_terraform",
        "//terraform-provider-constellation:tf_provider",
        "@terraform-plugin-docs//:bin/tfplugindocs",
    ],
    substitutions = {
        "@@TERRAFORM@@": "$(rootpath :com_github_hashicorp_terraform)",
        "@@TFPLUGINDOCS@@": "$(rootpath @terraform-plugin-docs//:bin/tfplugindocs)",
    },
    template = "terraform_docgen.sh.in",
)

sh_template(
    name = "version_info_gen",
    data = [
        "//hack/versioninfogen",
    ],
    substitutions = {
        "@@VERSIONINFOGEN@@": "$(rootpath //hack/versioninfogen:versioninfogen)",
    },
    template = "version_info_gen.sh.in",
)

alias(
    name = "com_github_katexochen_ghh",
    actual = select({
        "@io_bazel_rules_go//go/platform:darwin_amd64": "@com_github_katexochen_ghh_darwin_amd64//:ghh",
        "@io_bazel_rules_go//go/platform:darwin_arm64": "@com_github_katexochen_ghh_darwin_arm64//:ghh",
        "@io_bazel_rules_go//go/platform:linux_amd64": "@com_github_katexochen_ghh_linux_amd64//:ghh",
        "@io_bazel_rules_go//go/platform:linux_arm64": "@com_github_katexochen_ghh_linux_arm64//:ghh",
    }),
)

repo_command(
    name = "ghh",
    args = [],
    command = ":com_github_katexochen_ghh",
)

sh_template(
    name = "unused_gh_actions",
    data = [],
    substitutions = {},
    template = "unused_gh_actions.sh.in",
)

go_bin_for_host(
    name = "go_bin_for_host",
    visibility = ["//visibility:private"],
)

sh_template(
    name = "gocoverage_diff",
    data = [
        ":go_bin_for_host",
        "//hack/gocoverage",
    ],
    substitutions = {
        "@@GO@@": "$(rootpath :go_bin_for_host)",
        "@@GOCOVERAGE@@": "$(rootpath //hack/gocoverage:gocoverage)",
    },
    template = "gocoverage_diff.sh.in",
)

multirun(
    name = "tidy",
    commands = [
        ":shfmt",
        ":gofumpt",
        ":go_mod_tidy",
        ":gazelle_generate",
        ":buildifier_fix",
        ":terraform_fmt",
        ":buf_fmt",
        ":deps_mirror_fix",
        ":keep_sorted",
    ],
    jobs = 1,  # execute sequentially
    visibility = ["//visibility:public"],
)

multirun(
    name = "parallel_checks",
    testonly = True,
    commands = [
        ":gazelle_check",
        ":buildifier_check",
        ":terraform_check",
        ":golicenses_check",
        ":license_header_check",
        ":deps_mirror_check",
        ":proto_targets_check",
        ":unused_gh_actions",
    ] + select({
        "@io_bazel_rules_go//go/platform:darwin_arm64": [
            ":shellcheck_noop_warning",
            ":actionlint_no_shellcheck",
        ],
        "//conditions:default": [
            ":shellcheck",
            ":actionlint",
        ],
    }),
    jobs = 0,  # execute concurrently
    stop_on_error = False,
    visibility = ["//visibility:public"],
)

multirun(
    name = "check",
    testonly = True,
    commands = [
        ":parallel_checks",
        ":golangci_lint",
        # ":govulncheck", # Disabled since govulncheck blocks merging PRs while we have non critical Go vulnerabilities on main
    ],
    jobs = 1,  # execute sequentially to avoid running into memory issues on our CI runners
    stop_on_error = False,
    visibility = ["//visibility:public"],
)

multirun(
    name = "generate_files",
    commands = [
        ":terraform_gen",
        "//3rdparty/bazel/com_github_medik8s_node_maintainance_operator:pull_files",
        "//3rdparty/bazel/com_github_kubernetes_sigs_aws_load_balancer_controller:pull_files",
        ":go_generate",
        ":proto_generate",
    ],
    jobs = 0,  # execute concurrently
    visibility = ["//visibility:public"],
)

multirun(
    name = "generate_docs",
    commands = [
        ":cli_docgen",
        ":terraform_docgen",
    ],
    jobs = 0,  # execute concurrently
    visibility = ["//visibility:public"],
)

multirun(
    name = "generate",
    commands = [
        ":generate_files",
        ":generate_docs",
        ":version_info_gen",
    ],
    jobs = 1,  # execute sequentially
    visibility = ["//visibility:public"],
)
